#ifndef XH_AVCODECCONTROLER_H
#define XH_AVCODECCONTROLER_H
#include <QString>
#include <QSize>
#include <QQueue>
#include "xh_datadefine.h"
#include <QDateTime>

extern "C" {
    #include "libavcodec/avcodec.h"
    #include "libavformat/avformat.h"
    #include "libswscale/swscale.h"
    #include "libswresample/swresample.h"
    #include "libavutil/imgutils.h"
    #include "libavfilter/avfilter.h"
    #include "libavfilter/buffersink.h"
    #include "libavfilter/buffersrc.h"
};

enum MediaType{
    VIDEO = 0,
    MUSIC
};

enum MediaPlayStatus
{
    STATUS_PLAYING = 0,
    STATUS_PAUSE,
    STATUS_SEEK,
    STATUS_STOP
};

typedef void  (*UpdateVideo2GUI_Callback)    (H264YUV_Frame* yuv,unsigned long userData);
class MainWindow;

class xh_AVCodecControler
{
public:
    xh_AVCodecControler(MainWindow* mainWindow);
    ~xh_AVCodecControler();

    void setVideoPathString(const QString &videoPathString);
    int InitVideoCodec();
    QSize GetMediaWidthHeight();
    float GetMediaTotalSeconds();

    void StartPlayVideo();
    void StopPlayVideo();

    void startMediaProcessThreads();
    void waitAllThreadsExit();

    void setUpdateVideoCallback(const UpdateVideo2GUI_Callback &updateVideoCallback, unsigned long userDataVideo);

    void SetMediaStatusPlay();
    void SetMediaStatusPause();

    void seekMedia(float nPos, MediaType mediaType);

    void setSpeed(double speed);

    void setMuted(bool muted);
private:
    void doReadMediaFrameThread();
    void doVideoDecodeShowThread();
    void doAudioDecodePlayThread();

    void stdThreadSleep(int mseconds);

    void readMediaPacket();
    void freePacket(AVPacket* pkt);

    void tickVideoFrameTimerDelay(int64_t pts);
    void tickAudioFrameTimerDelay(int64_t pts);

    void convertAndRenderVideo(AVFrame* decodedFrame,long long ppts);
    void convertAndPlayAudio(AVFrame* decodedFrame);

    void copyDecodedFrame420(uint8_t* src, uint8_t* dist,int linesize, int width, int height);

    void recalculateStartTime();

    int initAudioFilter();

    int resampling(AVFrame* in, AVFrame** out);
private:
    MainWindow*             m_mainWindow = nullptr;

    AVRational              m_vStreamTimeRational;
    AVRational              m_aStreamTimeRational;

    MediaPlayStatus         m_eMediaPlayStatus;

    QString                 m_videoPathString;

    AVFormatContext*        m_formatCtx    = nullptr;

    AVCodecContext*         m_videoCodecCtx     = nullptr;
    AVCodecContext*         m_audioCodecCtx     = nullptr;

    int                     m_videoStreamIdx    = -1;
    int                     m_audioStreamIdx    = -1;

    int                     m_sampleRate = 48000;
    int                     m_sampleSize = 16;
    int                     m_channel = 2;

    AVFrame*                m_YUVFrame    = nullptr;

    uint8_t*                m_YUV420Buffer   = NULL;

    int                     m_videoWidth    = 0;
    int                     m_videoHeight   =0;


    QQueue<AVPacket *>      m_videoPktQueue;
    QQueue<AVPacket *>      m_audioPktQueue;

    bool                    m_bReadFileEOF = false;

    AVFrame*                m_pVideoFrame  = nullptr;
    AVFrame*                m_pAudioFrame = nullptr;

    SwsContext*             m_pVideoSwsCtx = nullptr;
    SwrContext*             m_pAudioSwrCtx = nullptr;

    uint8_t*                m_pSwrBuffer = nullptr;
    int                     m_swrBuffSize = 0;

    unsigned long               m_userDataVideo=0;
    UpdateVideo2GUI_Callback    m_updateVideoCallback =NULL;

    QDateTime               m_startTime;
    uint64_t                m_currVideoTimeStamp = 0;
    uint64_t                m_currAudioTimeStamp = 0;

    double                  m_speed = 1.0;

    //音频过滤器相关
    AVFilterGraph*          m_filterGraph = nullptr;
    AVFilterContext*        m_bufferSrcContext = nullptr;
    AVFilterContext*        m_bufferSinkContext = nullptr;

    //线程控制
    std::atomic<bool>       m_bThreadRunning;
    std::atomic<bool>       m_bFileThreadRunning;   //媒体读取线程
    std::atomic<bool>       m_bVideoThreadRunning;   //解码线程
    std::atomic<bool>       m_bAudioThreadRunning;
};

#endif // XH_AVCODECCONTROLER_H
